package cn.maihe.elg.operation.centers.guogu.config;

import cn.maihe.elg.operation.centers.guogu.auth.GuoGuAuthorization;
import cn.maihe.elg.operation.centers.guogu.auth.GuoGuCenterAuthConfig;
import cn.maihe.elg.operation.centers.guogu.auth.GuoGuEncryption;
import cn.maihe.elg.operation.config.ElgAuthConfig;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.utils.ValidateUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description 签名原描述：报文签名使用国密消息摘要算法（SM3），将报文字段按照ASCII升序排序，并按照“参数=参数值”的模式，用“&”字符拼接成字符串，最后使用appsecret对报文进行签名。
 * 加密原描述：电子保函服务平台对外交互接口统一使用国密算法（SM4），双方约定统一的秘钥Key值，详见示例代码，相关的数据加解密参见具体的接口。
 * @Author SSX
 * @Date 2025/03/18
 */
@Configuration
@ConfigurationProperties(prefix = "cn.maihe.elg.center-info-config")
@Getter
@Setter
public class GuoGuCenterInfosConfig {
    /**
     * key=CenterNoEnum.name.toLowerCase
     */
    private Map<String, CenterInfo> epointCenterMap = new HashMap<>();
    @JsonIgnore
    private final static Map<String, GuoGuCenterAuthConfig> authConfigMap = new HashMap<>();

    @Resource
    private ElgAuthConfig elgAuthConfig;

    private CenterNoEnum getByCenterNoEnum(String centerNoEnumName) {
        CenterNoEnum centerNoEnum = Arrays.stream(CenterNoEnum.values()).filter(o -> o.name().toLowerCase().equalsIgnoreCase(centerNoEnumName)).findFirst().orElse(null);
        Assert.notNull(centerNoEnum, "非法中心枚举名称[" + centerNoEnumName + "]");
        return centerNoEnum;
    }

    @PostConstruct
    public void init() {
        if (epointCenterMap != null && epointCenterMap.size() != 0) {
            epointCenterMap.entrySet().forEach(entry -> {
                CenterNoEnum centerNoEnum = getByCenterNoEnum(entry.getKey());
                getAuthConfig(centerNoEnum);
            });
        }
    }

    private CenterInfo getCenterInfo(CenterNoEnum centerNoEnum) {
        CenterInfo centerInfo = epointCenterMap.get(centerNoEnum.name().toLowerCase());
        Assert.notNull(centerInfo, () -> centerNoEnum + "未配置");
        try {
            ValidateUtil.validate(centerInfo);
        } catch (Exception e) {
            throw new RuntimeException("中心[" + centerNoEnum + "]配置信息错误");
        }

        return centerInfo;
    }

    /**
     * 根据新点各中心获取其配置信息
     *
     * @param centerNoEnum
     * @return
     */
    @JsonIgnore
    public GuoGuCenterAuthConfig getAuthConfig(CenterNoEnum centerNoEnum) {
        GuoGuCenterAuthConfig centerAuthConfig = authConfigMap.get(centerNoEnum.getCenterNo());
        if (centerAuthConfig == null) {
            CenterInfo centerInfo = this.getCenterInfo(centerNoEnum);
            GuoGuAuthorization authorization = new GuoGuAuthorization(elgAuthConfig, centerInfo);
            GuoGuEncryption encryption = new GuoGuEncryption(elgAuthConfig, centerInfo);

            centerAuthConfig = new GuoGuCenterAuthConfig(authorization, encryption, centerInfo);
            authConfigMap.put(centerNoEnum.getCenterNo(), centerAuthConfig);
        }

        return centerAuthConfig;
    }

    @Data
    public static class CenterInfo implements Serializable {
        /**
         * 签名验签 摘要算法SM3
         */
        @NotEmpty(message = "appKey不能为空")
        private String appKey;
        @NotEmpty(message = "appSecret不能为空")
        private String appSecret;

        /**
         * 双方约定统一的秘钥Key值 key值为base64编码过的值
         */
        @NotEmpty(message = "secretKey不能为空")
        private String secretKey;

        /**
         * 系统名称
         */
        @NotEmpty(message = "中心系统名称不能为空")
        private String sysName;

        /**
         * 请求平台接口地址前缀：不包含接口名称的
         */
        @NotEmpty(message = "中心url不能为空")
        private String url;
        /**
         * 投保申请结果通知通知完整地址：
         */
        private String baoHanNoticeUrl;
        /**
         * 退保通知接口完整地址：
         */
        private String quitNoticeUrl;
        /**
         * 理赔结果通知接口完整地址：
         */
        private String claimsResultNoticeUrl;
        private String downloadPublicKeyUrl;
        private String uploadFileUrl;
        private String fileCompleteUrl;



        /**
         * 保费费率百分几例如0.15即为0.15%
         */
        @NotEmpty(message = "保费费率不能为空")
        private String feeRate;
        /**
         * 保费保底金额：单位元
         */
        @NotNull(message = "保费保底金额不能为空")
        private Long minFeeYuan;
        /**
         * 16位sm4加密密钥
         */
        private String sm4Key;
        /**
         * 16位sm4加密向量
         */
        private String sm4Iv;

        /**
         * sm2私钥，base64
         */
        private String sm2PriKey;
        /**
         * sm2公钥，base64
         */
        private String sm2PubKey;

        /**
         * 同步支付结果至中心 0否，其他都是默认是
         */
        private String syncPayResult;

        /**
         * 同步支付结果至中心 0否，其他都是默认是
         */
        private Map<String, ClientInfo>  clientInfos;
    }

    @Data
    public static class ClientInfo implements Serializable {
        /**
         * 是	客户端ID
         */
        //@NotBlank(message = "客户端ID不能为空")
        private String clientId;
        /**
         * 是	客户端密钥
         */
        //@NotBlank(message = "客户端密钥不能为空")
        private String clientSecret;
        /**
         * 是	客户端公钥
         */
        //@NotBlank(message = "客户端公钥不能为空")
        private String clientPubKey;

        /**
         * 请求平台接口地址前缀：不包含接口名称的
         */
        //@NotEmpty(message = "中心url不能为空")
        private String url;
    }

}
